package tcnplanner;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashSet;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import tcnplanner.Item.ItemType;

public class Controller {

    private EntityManagerFactory emf = Persistence.createEntityManagerFactory("TCNplannerPU");
    private EntityManager em = emf.createEntityManager();
    private RoomService rooms = new RoomService();
    private ReservationService reservations = new ReservationService(em);
    private AccountService accounts = new AccountService(em);
    private Account currentUser = null;

    public boolean RegisterAccount(String username, String password, ActorType actorType, String name, String adres, String telephone, String email) {

        return accounts.create(new Account(username, password, actorType, name, adres, telephone, email));
    }

    public enum ActorType {

        INTERNCUSTOMER, EXTERNCUSTOMER, ENGINEER, PLANNER, OPERATOR, SFC
    };

    public Controller() {
       // loadTestReservations();
    }

    /*public boolean login(String username, String password) {
    return false;
    }
    
    public boolean logout() {
    }*/
    public boolean addReservation(Reservation r) {
        boolean res = false;
        em.getTransaction().begin();
        res = reservations.create(r);
        em.getTransaction().commit();
        return res;
    }

    public boolean editReservation(Reservation r) {
        boolean res = false;
        em.getTransaction().begin();
        res = reservations.updateReservation(r);
        em.getTransaction().commit();
        return res;
    }

    public Reservation findReservation(int id) {
        return reservations.find(id);
    }

    public ArrayList<Reservation> getAllReservations() {
        return reservations.findAll();
    }

    public ArrayList<Reservation> getScheduledReservations() {
        ArrayList<Reservation> scheduled = new ArrayList<Reservation>();
        for (Reservation r : getAllReservations()) {
            if (r.isScheduled()) {
                scheduled.add(r);
            }
        }
        return scheduled;
    }

    /*
     * externe klant
     * zelfde tijd/datum
     * 
     */
    public ArrayList<Reservation> getConflictedReservations() {
        ArrayList<Reservation> all = this.getAllReservations();
        HashSet<Reservation> conflicted = new HashSet<Reservation>();
        for (int i = 0; i < all.size(); i++) {
            for (int x = i + 1; x < all.size(); x++) {
                if (all.get(i).getReservationDate().before(all.get(x).getReservationDate())
                        && all.get(i).getEndDate().after(all.get(x).getReservationDate())) {
                    conflicted.add(all.get(x));
                    conflicted.add(all.get(i));
                }
                if (all.get(i).getReservationDate().before(all.get(x).getReservationDate())
                        && all.get(i).getEndDate().after(all.get(x).getEndDate())) {
                    conflicted.add(all.get(x));
                    conflicted.add(all.get(i));
                }
                if (all.get(x).getReservationDate().before(all.get(i).getReservationDate())
                        && all.get(x).getEndDate().after(all.get(i).getReservationDate())) {
                    conflicted.add(all.get(x));
                    conflicted.add(all.get(i));
                }
                if (all.get(x).getReservationDate().before(all.get(i).getReservationDate())
                        && all.get(x).getEndDate().after(all.get(i).getEndDate())) {
                    conflicted.add(all.get(x));
                    conflicted.add(all.get(i));
                }
                if (all.get(i).getReservationDate().equals(all.get(x).getReservationDate())
                        || all.get(i).getEndDate().equals(all.get(x).getEndDate())) {
                    conflicted.add(all.get(x));
                    conflicted.add(all.get(i));
                }
            }
        }
        return new ArrayList(conflicted);
    }

    /*
     * Serieuse fuck =)
     * Moet een lijst met met rooms teruggeven die vrij zijn tussen 
     * de aangegeven start en eindtijd.
     * @param start begin time of timeslot
     * @param end end time of timeslot
     * @return a list with available rooms.
     */
    public List<Testroom> getAvailableRooms(Date start, Date end) {
        ArrayList<Testroom> reserved = new ArrayList<Testroom>();
        for (Reservation res : reservations.findAll()) {
            if ((res.getStartDate().after(start) && res.getStartDate().before(end))
                    || (res.getEndDate().after(start) && res.getEndDate().before(end))) {
                reserved.add(res.getTestroom());
            }
        }

        ArrayList<Testroom> available = (ArrayList<Testroom>) rooms.findAll().clone();
        for (Testroom resroom : reserved) {
            Testroom remove = null;
            for (Testroom availroom : available) {
                if (resroom.getRoomNr() == availroom.getRoomNr()) {
                    remove = availroom;
                    break;
                }
            }
            if (remove != null) {
                available.remove(remove);
            }
        }

        return available;
    }

    /*
     * Returns a list of reservations that overlap with the given * reservation
     * @param r the reservation
     * @return the list of overlapping reservations
     */
    public List<Reservation> overlaps(Reservation res2) {
        ArrayList<Reservation> overlapping = new ArrayList<Reservation>();
        for (Reservation res1 : reservations.findAll()) {
            if ((res1.getStartDate().before(res2.getStartDate())
                    && res1.getEndDate().after(res2.getEndDate()))
                    || res2.getStartDate().before(res1.getStartDate())
                    && res2.getEndDate().after(res1.getEndDate())) {
                overlapping.add(res1);
            }
        }
        return overlapping;
    }

    public Account login(String username, String password) {
        Account account = accounts.find(username);
        if (account != null) {
            if (account.getPassword().equals(password)) {
                currentUser = account;
                return account;
            }
        }
        return null;
    }

    public Account getCurrentUser() {
        return currentUser;
    }

    private void loadTestReservations() {
        Test test1 = new Test(Test.TestType.FINALPRODUCT, "NextgenCPU", 1000);

        Account acc = this.login("LongN", "test");
        Account acc2 = this.login("AlbertL", "test");
        Account acc3 = this.login("TomasS", "test");
        Account acc4 = this.login("BobE", "test");

        TestSetup testsetup1 = new TestSetup();
        testsetup1.addItem(new Item("EG",ItemType.PROBER));
        testsetup1.addItem(new Item("TDP",ItemType.TDP));
        testsetup1.addItem(new Item("Multitest",ItemType.HANDLER));
        testsetup1.addItem(new Item("SPEA",ItemType.TESTER));

        TestSetup testsetup2 = new TestSetup();
        testsetup2.addItem(new Item("TSK",ItemType.PROBER));
        testsetup2.addItem(new Item("TDP",ItemType.TDP));
        testsetup2.addItem(new Item("ASM",ItemType.HANDLER));
        testsetup2.addItem(new Item("Vergiy",ItemType.TESTER));

        TestSetup testsetup3 = new TestSetup();
        testsetup3.addItem(new Item("EG",ItemType.PROBER));
        testsetup3.addItem(new Item("TDP",ItemType.TDP));
        testsetup3.addItem(new Item("Multitest",ItemType.HANDLER));
        testsetup3.addItem(new Item("Vergiy",ItemType.TESTER));


        Calendar cal = new GregorianCalendar();
        cal = Calendar.getInstance();
        cal.set(Calendar.MINUTE, 0);

        cal.add(Calendar.HOUR_OF_DAY, 1);
        Reservation res1 = new Reservation(cal.getTime(), new Testroom(1), testsetup1, test1, acc, "Hier kunnen eventuele comments geplaatst worden.");
        res1.setBatch(new Batch(20));

        cal.add(Calendar.HOUR, 6);
        int dfa = cal.get(cal.HOUR);
        Date date = cal.getTime();
        int di = date.getHours();
        date = new Date(2011,9,9,9,9,9);
        di = date.getHours();
        Reservation res2 = new Reservation(date, new Testroom(1), testsetup2, test1, acc2, "Hier kunnen eventuele comments geplaatst worden.");
        res2.setBatch(new Batch(20));

        cal.add(Calendar.HOUR_OF_DAY, 20);
        Reservation res3 = new Reservation(cal.getTime(), new Testroom(1), testsetup1, test1, acc2, "Hier kunnen eventuele comments geplaatst worden.");
        res3.setBatch(new Batch(20));

        //cal.add(Calendar.HOUR_OF_DAY, 6); zelfde tijd als vorige dus dus
        Reservation res4 = new Reservation(cal.getTime(), new Testroom(1), testsetup3, test1, acc, "Hier kunnen eventuele comments geplaatst worden.");
        res4.setBatch(new Batch(20));
        
        cal.add(Calendar.HOUR_OF_DAY, 6);
        Reservation res5 = new Reservation(cal.getTime(), new Testroom(1), testsetup2, test1, acc3, "Hier kunnen eventuele comments geplaatst worden.");
        res5.setBatch(new Batch(20));

        cal.add(Calendar.HOUR_OF_DAY, 4);
        Reservation res6 = new Reservation(cal.getTime(), new Testroom(1), testsetup1, test1, acc4, "Hier kunnen eventuele comments geplaatst worden.");
        res6.setBatch(new Batch(20));

        cal.add(Calendar.HOUR_OF_DAY, 7);
        Reservation res7 = new Reservation(cal.getTime(), new Testroom(1), testsetup3, test1, acc2, "Hier kunnen eventuele comments geplaatst worden.");
        res7.setBatch(new Batch(20));

        addReservation(res1);
        addReservation(res2);
        addReservation(res3);
        addReservation(res4);
        addReservation(res5);
        addReservation(res6);
        addReservation(res7);
    }
}
